package com.alex.formates.qd;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Vector;

import android.util.Log;

import com.alex.books.BaseBook;
import com.alex.books.Chapter;
import com.alex.formates.ReaderPlugin;

/**
 * 
 * 解析txt文件
 * 
 * @author Alex.Lu
 * 
 */
public class TXTPlugin extends ReaderPlugin {

	private int mBufBegin;
	private int mBufEnd;
	private byte[] bytes;
	private long mMbBufLen;


	@Override
	public Object decode(BaseBook book, File file) {
		// TODO Auto-generated method stub

		mMbBufLen = file.length();
		bytes = new byte[(int) mMbBufLen];

		try {
			FileInputStream fis = new FileInputStream(file);
			fis.read(bytes);
			fis.close();
		} catch (FileNotFoundException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		mBufBegin = mBufEnd = (int) book.mReaderingInfo.mMarkPos;

		return null;
	}

	@Override
	public boolean isFirstChapter() {
		// TODO Auto-generated method stub
		if (mBaseBook.mReaderingInfo.mIndex <= 0) {
			return true;
		}
		return false;
	}

	@Override
	public boolean isLastChapter() {
		// TODO Auto-generated method stub
		if (mBaseBook.mReaderingInfo.mIndex >= mBaseBook.mChapters.size() - 1) {
			return true;
		}
		return false;
	}

	@Override
	public boolean isFirstPage() {
		// TODO Auto-generated method stub
		if (mBaseBook.mReaderingInfo.mIndex <= 0
				&& mBufBegin <= mBaseBook.mChapters.get(0).mPosBegin) {
			return true;
		}
		return false;
	}

	@Override
	public boolean isLastPage() {
		// TODO Auto-generated method stub
		if (mBaseBook.mReaderingInfo.mIndex >= mBaseBook.mChapters.size() - 1
				&& mBufEnd >= mBaseBook.mReaderingInfo.mCurChapter.mPosEnd) {
			return true;
		}
		return false;
	}

	@Override
	public String nextChapter() {
		// TODO Auto-generated method stub
		if (mBaseBook.mReaderingInfo.mIndex + 1 < mBaseBook.mChapters.size()) {
			mBaseBook.mReaderingInfo.mIndex++;
			mBaseBook.mReaderingInfo.mCurChapter = mBaseBook.mChapters
					.get(mBaseBook.mReaderingInfo.mIndex);
			mBaseBook.mReaderingInfo.mMarkPos = mBaseBook.mReaderingInfo.mCurChapter.mPosBegin;
		}
		mBufEnd = (int) mBaseBook.mReaderingInfo.mMarkPos;
		StringBuffer text = new StringBuffer();
		mLines.clear();
		mLines = getPageNextText(mBaseBook.mReaderingInfo.mCurChapter.mPosEnd);
		for (int i = 0; i < mLines.size(); i++) {
			text.append(mLines.get(i) + "\n");
		}
		mBaseBook.mReaderingInfo.mCurText = text.toString();
		return text.toString();
	}

	@Override
	public String nextPage() {
		// TODO Auto-generated method stub
		Log.d("nextPage", "" + mBufEnd + " "
				+ mBaseBook.mReaderingInfo.mCurChapter.mPosEnd + "  "
				+ mBaseBook.mReaderingInfo.mIndex + "  "
				+ mBaseBook.mChapters.size());
		if (mBufEnd >= mBaseBook.mReaderingInfo.mCurChapter.mPosEnd
				&& mBaseBook.mReaderingInfo.mIndex + 1 < mBaseBook.mChapters
						.size()) {
			mBaseBook.mReaderingInfo.mIndex++;
			mBaseBook.mReaderingInfo.mCurChapter = mBaseBook.mChapters
					.get(mBaseBook.mReaderingInfo.mIndex);
			mBaseBook.mReaderingInfo.mMarkPos = mBaseBook.mReaderingInfo.mCurChapter.mPosBegin;
			mBufEnd = (int) mBaseBook.mReaderingInfo.mCurChapter.mPosBegin;
		}

		StringBuffer text = new StringBuffer();
		mLines.clear();
		mLines = getPageNextText(mBaseBook.mReaderingInfo.mCurChapter.mPosEnd);
		for (int i = 0; i < mLines.size(); i++) {
			text.append(mLines.get(i) + "\n");
			Log.d("nextPage" + i, "text:" + mLines.get(i));
		}
		mBaseBook.mReaderingInfo.mCurText = text.toString();
		return text.toString();
	}

	@Override
	public String previousChapter() {
		// TODO Auto-generated method stub
		if (mBaseBook.mReaderingInfo.mIndex - 1 >= 0) {
			mBaseBook.mReaderingInfo.mIndex--;
			mBaseBook.mReaderingInfo.mCurChapter = mBaseBook.mChapters
					.get(mBaseBook.mReaderingInfo.mIndex);
			mBaseBook.mReaderingInfo.mMarkPos = mBaseBook.mReaderingInfo.mCurChapter.mPosBegin;
		}
		mBufEnd = (int) mBaseBook.mReaderingInfo.mMarkPos;
		StringBuffer text = new StringBuffer();
		mLines.clear();
		mLines = getPageNextText(mBaseBook.mReaderingInfo.mCurChapter.mPosEnd);
		for (int i = 0; i < mLines.size(); i++) {
			text.append(mLines.get(i) + "\n");
		}
		mBaseBook.mReaderingInfo.mCurText = text.toString();
		return text.toString();
	}

	@Override
	public String previousPage() {
		// TODO Auto-generated method stub
		if (mBufBegin <= mBaseBook.mReaderingInfo.mCurChapter.mPosBegin
				&& mBaseBook.mReaderingInfo.mIndex - 1 >= 0) {
			mBaseBook.mReaderingInfo.mIndex--;
			mBaseBook.mReaderingInfo.mCurChapter = mBaseBook.mChapters
					.get(mBaseBook.mReaderingInfo.mIndex);
			mBaseBook.mReaderingInfo.mMarkPos = mBaseBook.mReaderingInfo.mCurChapter.mPosEnd;
			mBufBegin = (int) mBaseBook.mReaderingInfo.mMarkPos;
		}

		StringBuffer text = new StringBuffer();
		mLines.clear();
		mLines = getPagePrevious();
		/*
		 * if(mBufBegin <= mBaseBook.mReaderingInfo.mCurChapter.mPosBegin){
		 * mBufEnd = (int)mBaseBook.mReaderingInfo.mCurChapter.mPosBegin; mLines
		 * = getPageNextText(mBaseBook.mReaderingInfo.mCurChapter.mPosEnd); }
		 */

		for (int i = 0; i < mLines.size(); i++) {
			text.append(mLines.get(i) + "\n");
			Log.d("previousPage " + i, mLines.get(i));
		}
		mBaseBook.mReaderingInfo.mCurText = text.toString();
		return text.toString();
	}

	@Override
	public String refreshPage() {
		// TODO Auto-generated method stub
		mBufEnd = (int) mBaseBook.mReaderingInfo.mMarkPos;
		StringBuffer text = new StringBuffer();
		mLines.clear();
		mLines = getPageNextText(Integer.valueOf(mBaseBook.mWordNumber));
		for (int i = 0; i < mLines.size(); i++) {
			text.append(mLines.get(i) + "\n");
			Log.d("nextPage" + i, "text:" + mLines.get(i));
		}
		mBaseBook.mReaderingInfo.mCurText = text.toString();
		return text.toString();
	}

	
	public Object generatedCatalog2(BaseBook book, File file,String keywords) {
		Vector<Chapter> vec = new Vector<Chapter>();
		mMbBufLen = file.length();
		bytes = new byte[(int) mMbBufLen];
		
		try {
			FileInputStream fis = new FileInputStream(file);
			fis.read(bytes);
			fis.close();
		} catch (FileNotFoundException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		int postion = 0;
		int beginPos = 0;
		String strParagraph = "";
		String chapterName = "";
		while (postion < mMbBufLen) {
			long endPos = mMbBufLen;
			byte[] paraBuf = readParagraphNext(postion);
			//postion += paraBuf.length;
			try {
				strParagraph = new String(paraBuf, mStrCharsetName);
			} catch (UnsupportedEncodingException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			if (strParagraph.length() < 20 && strParagraph.contains(keywords)) {
				
				if (beginPos == 0) {
					beginPos = postion;
				} else {
					endPos = postion - paraBuf.length;
					Chapter chapter = new Chapter();
					chapter.mBookId = book.mBookId;
					chapter.mChapterName = chapterName;
					chapter.mPosBegin = beginPos;
					chapter.mPosEnd = (int) endPos;
					chapter.mLength = chapter.mPosEnd - chapter.mPosBegin;
					vec.add(chapter);
					beginPos = postion;
				}
				chapterName = strParagraph;
			}
			postion += paraBuf.length;
		}
		Chapter chapter = new Chapter();
		chapter.mBookId = book.mBookId;
		chapter.mChapterName = chapterName;
		chapter.mPosBegin = beginPos;
		chapter.mPosEnd = postion;
		chapter.mLength = chapter.mPosEnd - chapter.mPosBegin;
		vec.add(chapter);
		book.mChapters = vec;
		book.mChapterNumber = "" + book.mChapters.size();
		book.mWordNumber = String.valueOf(postion);
		return vec;
	}

	@Override
	public Object generatedCatalog(BaseBook book, File file, int mode) {
		// TODO Auto-generated method stub

		Vector<Chapter> vec = new Vector<Chapter>();
		mMbBufLen = file.length();
		bytes = new byte[(int) mMbBufLen];
		
		try {
			FileInputStream fis = new FileInputStream(file);
			fis.read(bytes);
			fis.close();
		} catch (FileNotFoundException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		int postion = 0;
		int beginPos = 0;
		String strParagraph = "";
		String chapterName = "";
		while (postion < mMbBufLen) {
			long endPos = mMbBufLen;
			byte[] paraBuf = readParagraphNext(postion);
			//postion += paraBuf.length;
			try {
				strParagraph = new String(paraBuf, mStrCharsetName);
			} catch (UnsupportedEncodingException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			if (strParagraph.length() < 20 && strParagraph.contains("章")) {
				
				if (beginPos == 0) {
					beginPos = postion;
				} else {
					endPos = postion - paraBuf.length;
					Chapter chapter = new Chapter();
					chapter.mBookId = book.mBookId;
					chapter.mChapterName = chapterName;
					chapter.mPosBegin = beginPos;
					chapter.mPosEnd = (int) endPos;
					chapter.mLength = chapter.mPosEnd - chapter.mPosBegin;
					vec.add(chapter);
					beginPos = postion;
				}
				chapterName = strParagraph;
			}
			postion += paraBuf.length;
		}
		Chapter chapter = new Chapter();
		chapter.mBookId = book.mBookId;
		chapter.mChapterName = book.mBookName;
		chapter.mPosBegin = beginPos;
		chapter.mPosEnd = mMbBufLen;
		chapter.mLength = chapter.mPosEnd - chapter.mPosBegin;
		vec.add(chapter);
		book.mChapters = vec;
		book.mChapterNumber = "" + book.mChapters.size();
		book.mWordNumber = String.valueOf(mMbBufLen);
		
		try {
			book.mAboutBook = new String(readParagraphNext(0), mStrCharsetName);
		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		};
		return vec;
	}

	private String mStrCharsetName = "GBK";

	private byte[] readSectionName(int nFromPos) {
		int nStart = nFromPos;
		int i = nStart;
		byte b0, b1;
		if (mStrCharsetName.equals("UTF-16LE")) {
			while (i < mMbBufLen - 1) {
				b0 = bytes[i++];
				b1 = bytes[i++];
				if (b0 == 0x0a && b1 == 0x00) {
					break;
				}
			}
		} else if (mStrCharsetName.equals("UTF-16BE")) {
			while (i < mMbBufLen - 1) {
				b0 = bytes[i++];
				b1 = bytes[i++];
				if (b0 == 0x00 && b1 == 0x0a) {
					break;
				}
			}
		} else {
			while (i < mMbBufLen) {
				b0 = bytes[i++];
				if (b0 == 0x0a) {
					break;
				}
			}
		}
		int nParaSize = i - nStart;
		byte[] buf = new byte[nParaSize];
		for (i = 0; i < nParaSize; i++) {
			buf[i] = bytes[nFromPos + i];
		}
		return buf;
	}

	private byte[] readParagraphNext(int nFromPos) {
		int nStart = nFromPos;
		int i = nStart;
		byte b0, b1;
		if (mStrCharsetName.equals("UTF-16LE")) {
			while (i < mMbBufLen - 1) {
				b0 = bytes[i++];
				b1 = bytes[i++];
				if (b0 == 0x0a && b1 == 0x00) {
					break;
				}
			}
		} else if (mStrCharsetName.equals("UTF-16BE")) {
			while (i < mMbBufLen - 1) {
				b0 = bytes[i++];
				b1 = bytes[i++];
				if (b0 == 0x00 && b1 == 0x0a) {
					break;
				}
			}
		} else {
			while (i < mMbBufLen) {
				b0 = bytes[i++];
				if (b0 == 0x0a) {
					break;
				}
			}
		}
		int nParaSize = i - nStart;
		byte[] buf = new byte[nParaSize];
		for (i = 0; i < nParaSize; i++) {
			buf[i] = bytes[nFromPos + i];
		}
		return buf;
	}
	
	private byte[] readParagraphNext0(int nFromPos) {
		int nStart = nFromPos;
		int i = nStart;
		byte b0, b1;
		
		while (i < 200&& i < mMbBufLen) {
			b0 = bytes[i++];
			if (b0 == 0x0a) {
				break;
			}
		}
		
		int nParaSize = i - nStart;
		byte[] buf = new byte[nParaSize];
		for (i = 0; i < nParaSize; i++) {
			buf[i] = bytes[nFromPos + i];
		}
		return buf;
	}

	/**
	 * 获取下一页数据
	 * 
	 * @param endPos
	 * @return
	 */
	private Vector<String> getPageNextText(long endPos) {
		mBaseBook.mReaderingInfo.mMarkPos = mBufEnd;
		mBufBegin = mBufEnd;
		String strParagraph = "";
		Vector<String> lines = new Vector<String>();
		while (lines.size() <= 0) {
			while (lines.size() < mReaderFormate.mLineCount && mBufEnd < endPos) {
				byte[] paraBuf = readParagraphNext(mBufEnd);
				mBufEnd += paraBuf.length;
				try {
					strParagraph = new String(paraBuf, mStrCharsetName);
				} catch (UnsupportedEncodingException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				String strReturn = "";
				if (strParagraph.indexOf("\r\n") != -1) {
					strReturn = "\r\n";
					strParagraph = strParagraph.replaceAll("\r\n", "");
				} else if (strParagraph.indexOf("\n") != -1) {
					strReturn = "\n";
					strParagraph = strParagraph.replaceAll("\n", "");
				}

				if (strParagraph.length() == 0) {
					lines.add(strParagraph);
				}
				while (strParagraph.length() > 0) {
					int nSize = mReaderFormate.mPaint.breakText(strParagraph,
							true, mReaderFormate.mPageW, null);

					lines.add(strParagraph.substring(0, nSize));
					strParagraph = strParagraph.substring(nSize);
					if (lines.size() >= mReaderFormate.mLineCount) {
						break;
					}
				}
				if (strParagraph.length() != 0) {
					try {
						mBufEnd -= (strParagraph + strReturn)
								.getBytes(mStrCharsetName).length;
					} catch (UnsupportedEncodingException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
			}
		}
		return lines;
	}

	private Vector<String> getPagePrevious() {
		if (mBufBegin <= mBaseBook.mChapters.get(0).mPosBegin)
			mBufBegin = (int) mBaseBook.mChapters.get(0).mPosBegin;
		mBufEnd = mBufBegin;
		Vector<String> lines = new Vector<String>();
		String strParagraph = "";
		while (lines.size() <= 0) {
			while (lines.size() < mReaderFormate.mLineCount && mBufBegin >= 0) {
				Vector<String> paraLines = new Vector<String>();
				byte[] paraBuf = readParagraphPrevious(mBufBegin);
				mBufBegin -= paraBuf.length;

				try {
					strParagraph = new String(paraBuf, mStrCharsetName);
				} catch (UnsupportedEncodingException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				strParagraph = strParagraph.replaceAll("\r\n", "");
				strParagraph = strParagraph.replaceAll("\n", "");
				if (strParagraph.length() == 0) {
					paraLines.add(strParagraph);
				}
				while (strParagraph.length() > 0) {
					int nSize = mReaderFormate.mPaint.breakText(strParagraph,
							true, mReaderFormate.mPageW, null);
					paraLines.add(strParagraph.substring(0, nSize));
					strParagraph = strParagraph.substring(nSize);
				}
				lines.addAll(0, paraLines);
			}
			while (lines.size() > mReaderFormate.mLineCount) {
				try {
					mBufBegin += lines.get(0).getBytes(mStrCharsetName).length;
					lines.remove(0);
				} catch (UnsupportedEncodingException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
		mBaseBook.mReaderingInfo.mMarkPos = mBufBegin;
		return lines;
	}

	/**
	 * 读取上一段落
	 * 
	 * @param nFromPos
	 * @return
	 */
	private byte[] readParagraphPrevious(int nFromPos) {
		int nEnd = nFromPos;
		int i;
		i = nEnd - 1;
		byte b;
		while (i > 0) {
			b = bytes[i];
			if (b == 0x0a && i != nEnd - 1) {
				i++;
				break;
			}
			i--;
		}
		if (i < 0)
			i = 0;
		int nParaSize = nEnd - i;
		int j;
		byte[] buf = new byte[nParaSize];
		for (j = 0; j < nParaSize; j++) {
			buf[j] = bytes[i + j];
		}
		return buf;
	}
}
